namespace Domotica.Media
{
    using Microsoft.VisualBasic;
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.Runtime.CompilerServices;
    using WMPLib;

    public class MediaPlayer : INotifyPropertyChanged
    {
        private static List<WeakReference> __ENCList = new List<WeakReference>();
        private AlbumList _Albums;
        private ArtistList _Artists;
        private Track _CurrentMedia;
        private SortedDictionary<string, Track> _TracksById;
        private WindowsMediaPlayer _wmp;

        public event MediaPlayerDelegate CurrentMediaChange;

        public event PropertyChangedEventHandler PropertyChanged;


        public MediaPlayer()
        {
            List<WeakReference> list = __ENCList;
            lock (list)
            {
                __ENCList.Add(new WeakReference(this));
            }
            this._TracksById = new SortedDictionary<string, Track>();
            this._Artists = new ArtistList();
            this._Albums = new AlbumList();
            this.Init();
        }

        private void AddEventHandlers()
        {
            this._wmp.CurrentItemChange +=(this.DoCurrentItemChange);
        }

        private void DoCurrentItemChange(object mediaObject)
        {
            string uId = ((IWMPMedia) mediaObject).getItemInfo("UniqueFileIdentifier");
            this.CurrentMedia = this._TracksById[uId];
        }

        protected void DoCurrentMediaChange(EventArgs e)
        {
            MediaPlayerDelegate c = this.CurrentMediaChange;
            if (c != null)
            {
                c(this, e);
            }
        }

        protected void DoPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler c = this.PropertyChanged;
            if (c != null)
            {
                c(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        private void Init()
        {
            this._wmp = new WindowsMediaPlayerClass();
            this.AddEventHandlers();
            this.Load();
        }

        private void Load()
        {
            IWMPPlaylist playlist = ((IWMPMediaCollection2) this._wmp.mediaCollection).getByAttribute("MediaType", "audio");
            Dictionary<string, Artist> artistDictionary = new Dictionary<string, Artist>();
            DictionaryCollection<string, Album> albumsDictionary = new DictionaryCollection<string, Album>();
            int count = playlist.count - 1;
            for (int i = 0; i <= count; i++)
            {
                IWMPMedia media = playlist.get_Item(i);
                string albumArtistName = media.getItemInfo("AlbumArtist");
                string albumName = media.getItemInfo("Album");
                Artist theArtist = null;
                string artistSortName = Artist.GetSortName(albumArtistName);
                if (!artistDictionary.TryGetValue(artistSortName, out theArtist))
                {
                    theArtist = new Artist(albumArtistName);
                    artistDictionary.Add(artistSortName, theArtist);
                }
                Album theAlbum = null;
                if (!theArtist.Albums.TryGetValue(albumName, ref theAlbum))
                {
                    theAlbum = new Album(albumName, theArtist);
                    theArtist.Albums.Add(albumName, theAlbum);
                    Album dummy = null;
                    if (albumsDictionary.TryGetValue(albumName, ref dummy))
                    {
                        int a = 0;
                        while (albumsDictionary.TryGetValue(albumName + " (" + a.ToString() + ")", ref dummy))
                        {
                            a++;
                        }
                        albumsDictionary.Add(albumName + " (" + a.ToString() + ")", theAlbum);
                    }
                    else
                    {
                        albumsDictionary.Add(albumName, theAlbum);
                    }
                }
                Track theTrack = new Track(media, theAlbum);
                if (!this._TracksById.ContainsKey(theTrack.UniqueFileIdentifier))
                {
                    this._TracksById.Add(theTrack.UniqueFileIdentifier, theTrack);
                }
                theAlbum.Tracks.Add(theTrack);
            }
            this._Artists.AddRange(artistDictionary.Values);
            this._Artists.Sort();
            this._Albums.AddRange(albumsDictionary.Values);
            this._Albums.Sort();
        }

        public void NextTrack()
        {
            this._wmp.controls.next();
        }

        public void Play()
        {
            this._wmp.controls.play();
        }

        public void Play(Album album)
        {
            IWMPPlaylist l = this._wmp.mediaCollection.getByAlbum(album.Name);
            if (l!= null)
            {
                this._wmp.currentPlaylist = l;
            }
        }

        public void Play(Artist artist)
        {
            IWMPPlaylist l = this._wmp.mediaCollection.getByAttribute("AlbumArtist", artist.Name);
            if (l != null)
            {
                this._wmp.currentPlaylist = l;
            }
        }

        public void Play(Track track)
        {
            this._wmp.currentMedia = track.MediaItem;
        }

        public void PreviousTrack()
        {
            this._wmp.controls.previous();
        }

        public void Stop()
        {
            this._wmp.controls.stop();
        }

        public AlbumList Albums
        {
            get
            {
                return this._Albums;
            }
        }

        public ArtistList Artists
        {
            get
            {
                return this._Artists;
            }
        }

        public Track CurrentMedia
        {
            get
            {
                return this._CurrentMedia;
            }
            private set
            {
                Track media = value;
                this._CurrentMedia = value;
                if (media == null && value == null)
                {}
                else if (media!=null && value==null)
                {
                    this.DoPropertyChanged("CurrentMedia");
                }
                else if (media == null)
                {
                    this.DoPropertyChanged("CurrentMedia");
                }
                else if (media.UniqueFileIdentifier != value.UniqueFileIdentifier)
                {
                    this.DoPropertyChanged("CurrentMedia");
                }
            }
        }

        public int Volume
        {
            get
            {
                return this._wmp.settings.volume;
            }
            set
            {
                this._wmp.settings.volume = value;
            }
        }
    }
}

